home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / ForCLI / HexD2.lha / HexD.a < prev    next >
Text File  |  1993-02-21  |  32KB  |  1,396 lines

  1. *
  2. * HexD. A program that quickly dumps any file(s) in hex format on standard
  3. * out or a file.
  4. *
  5. * Version history:
  6. *
  7. * Magnus Holmgren:
  8. * V1.0  24-11-91 : First release (portable C-code).
  9. *
  10. * V2.0  21-02-93 : Not portable any more, requires AmigaDOS 2.0.
  11. *                : Downcoded to assembler. Many enhanchements.
  12. *
  13. * Warning: This source is a bit messy! Major cleanup could be done. But
  14. * that would make the program larger! :) :)
  15. *
  16.  
  17.     OPT    O+,D-
  18.  
  19.     INCDIR    INC:
  20.     INCLUDE    exec/types.i
  21.     INCLUDE    exec/funcdef.i
  22.     INCLUDE    exec/alerts.i
  23.     INCLUDE    exec/execbase.i
  24.     INCLUDE    exec/exec_lib.i
  25.     INCLUDE    exec/memory.i
  26.     INCLUDE    dos/dosasl.i
  27.     INCLUDE    dos/dosextens.i
  28.     INCLUDE    dos/dos_lib.i
  29.     INCLUDE    graphics/text.i
  30.     INCLUDE    intuition/intuition.i
  31.  
  32.  
  33. *
  34. * Flags structure
  35. *
  36.  
  37.     STRUCTURE Flags,0
  38.     APTR    f_Files            ; The files to show
  39.     APTR    f_To            ; Output file
  40.     APTR    f_Width            ; Width of output
  41.     LONG    f_All            ; Enter subdirectories?
  42.     LONG    f_Append        ; Append to TO file?
  43.     LONG    f_Hex            ; Hex only output?
  44.     LONG    f_Ascii            ; Ascii only output?
  45.     LONG    f_NoOffset        ; Show offset?
  46.     LONG    f_Header        ; Show a header?
  47.     LONG    f_Cursor        ; Hide cursor?
  48.     LONG    f_Page            ; Show page prompt?
  49.     LABEL    f_SIZEOF        ; Size of flags struct
  50.  
  51. * To make it easier to keep both up-to-date
  52.  
  53. TEMPLATE    MACRO
  54.         dc.b    "FILES/M,TO/K,WIDTH/K/N,ALL/S,APPEND/S,HEX/S,ASCII/S,"
  55.         dc.b    "NOOFFSET/S,HEADER/S,CURSOR/S,PAGE/S",0
  56.         ENDM
  57.  
  58. * Maximum length allowed for one filename
  59.  
  60. FILENAMESIZE    EQU    512
  61.  
  62. * Maximum width to display on screen. Minimal width is "floating"...
  63.  
  64. MAXWIDTH    EQU    512
  65.  
  66. * Default width (if out file is interactive, get default from there instead)
  67.  
  68. DEFWIDTH    EQU    75
  69.  
  70. * Starting value for the dt_YPos variable
  71.  
  72. INITYPOS    EQU    3
  73.  
  74. *
  75. * Data structure. All data used by us. Gets allocated, for purity.
  76. *
  77.  
  78.     STRUCTURE DataTable,0
  79.     APTR    dt_DOSBase
  80.     APTR    dt_SysBase
  81.     APTR    dt_InitialSP        ; Stack pointer at start
  82.     APTR    dt_InFile        ; File we currently are reading
  83.     APTR    dt_OutFile        ; File we are writing data to
  84.     APTR    dt_RdArgs        ; RDArgs structure
  85.     STRUCT    dt_Flags,f_SIZEOF    ; Flags array
  86.     ALIGNLONG            ; Better long-align AnchorPath (probably not needed here)
  87.     STRUCT    dt_AP,ap_SIZEOF        ; AnchorPath, for pattern matching
  88.     STRUCT    dt_APNameBuffer,FILENAMESIZE    ; Filename buffer (part of AnchorPath)
  89.     ALIGNLONG            ; Long align again, for speed
  90.     STRUCT    dt_ReadBuffer,MAXWIDTH+2    ; Buffer for reading data
  91.     ALIGNLONG            ; Long align again, for speed
  92.     STRUCT    dt_WriteBuffer,MAXWIDTH+2    ; Buffer while building output string
  93.     ALIGNWORD            ; Better word-align
  94.     LONG    dt_BytePos        ; Byte position in file
  95.     UWORD    dt_Width        ; Number of chars/row
  96.     UWORD    dt_Height        ; Number of rows (for pager if > 0)
  97.     UWORD    dt_YPos            ; Current output line (for pager)
  98.     UWORD    dt_MinWidth        ; Minimal width allowed
  99.     UWORD    dt_EndOfHex        ; Position on line at which hex part ends
  100.     UWORD    dt_Response        ; Buffer for pager
  101.     UBYTE    dt_DisplayFormat    ; How to show the data
  102.     UBYTE    dt_OutOpened        ; We have opened Out (cleanup)
  103.     UBYTE    dt_InOpened        ; We have opened In (cleanup)
  104.     UBYTE    dt_Matching        ; An MatchFirst() have been used without,
  105.                     ; a corresponding MatchEnd() (cleanup).
  106.     LABEL    dt_SIZEOF        ; Size of data table
  107.  
  108.  
  109. *
  110. * Different values in dt_DisplayFormat byte:
  111. *
  112.  
  113. BOTH    EQU    0            ; Both Ascii and Hex
  114. ASCII    EQU    1            ; Only Ascii
  115. HEX    EQU    2            ; Only Hex
  116.  
  117. *
  118. * Macro to generate the "minimal width array". Take the dt_DisplayFormat
  119. * byte, add NOOFFSET (currently 4) if f_NoOffset is TRUE, and use that value
  120. * (shifted properly) to index in this word-array, to get the *REAL* minimal
  121. * width (in chars) allowed.
  122. *
  123.  
  124. NOOFFSET    EQU    4
  125.  
  126. MINWIDTHARRAY    MACRO
  127.     dc.w    14,11,10,0,6,3,2,0
  128.     ENDM
  129.  
  130. * A few handy macros
  131.  
  132. * Call a library routine
  133.  
  134. SYS    MACRO
  135.     jsr    _LVO\1(a6)
  136.     ENDM
  137.  
  138. * Call a subroutine
  139.  
  140. CALL    MACRO
  141.     bsr    \1
  142.     ENDM
  143.  
  144. * Quickly clear a data register
  145.  
  146. CLD    MACRO
  147.     moveq    #0,d\1
  148.     ENDM
  149.  
  150. * Quickly clear an address register
  151.  
  152. CLA    MACRO
  153.     sub.l    a\1,a\1
  154.     ENDM
  155.  
  156. *
  157. * Push register list to stack. Remembers the last list used. If 'NOREM'
  158. * is the second argument, the pushed list will not be remembered.
  159. *
  160.  
  161. PUSHM    MACRO
  162.     movem.l    \1,-(sp)
  163.     IFNC    '\2','NOREM'
  164. PUSHM_COUNT        SET    PUSHM_COUNT+1
  165. PUSHM_\<PUSHM_COUNT>    REG     \1
  166.     ENDC
  167.     ENDM
  168.  
  169. *
  170. * Restore register list from stack. If no argument, restore last register
  171. * list remembered.
  172. *
  173.  
  174. POPM    MACRO
  175.     IFC    '\1',''
  176.     movem.l (sp)+,PUSHM_\<PUSHM_COUNT>
  177.     ELSEIF
  178.     movem.l    (sp)+,\1
  179.     ENDC
  180.     ENDM
  181.  
  182. *
  183. * Works like PUSHM, but works on single registers only (needed since GenIm2
  184. * won't optimize "single-register movem" :( ).
  185. *
  186.  
  187. PUSH    MACRO
  188.     move.l    \1,-(sp)
  189.     IFNC    '\2','NOREM'
  190. PUSH_COUNT        SET    PUSH_COUNT+1
  191. PUSH_\<PUSH_COUNT>    EQUR    \1
  192.     ENDC
  193.     ENDM
  194.  
  195. *
  196. * Like POPM, but a signle register.
  197. *
  198.  
  199. POP    MACRO
  200.     IFC    '\1',''
  201.     move.l (sp)+,PUSH_\<PUSH_COUNT>
  202.     ELSEIF
  203.     move.l    (sp)+,\1
  204.     ENDC
  205.     ENDM
  206.  
  207. * Init some counters for the PUSH(M)/POP(M) macros
  208.  
  209. PUSHM_COUNT    SET    0
  210. PUSH_COUNT    SET    0
  211.  
  212.  
  213.     SECTION    Code,CODE
  214.  
  215. *
  216. * Init data area, open needed libraries.
  217. *
  218.  
  219. Init    move.l    4.w,a6            ; First get SysBase
  220.     CLA    1
  221.     SYS    FindTask
  222.     move.l    d0,a5            ; Our process struct
  223.     lea    DOSName_Msg(pc),a1    ; dos.library
  224.     CLD    0            ; Any version
  225.     SYS    OpenLibrary        ; Try to open it
  226.     move.l    d0,a3            ; Save DOSBase
  227.     tst.l    d0            ; Did we get it?
  228.     bne.b    .dos_ok            ; Yep
  229.  
  230.     move.l    #AT_Recovery|AG_OpenLib|AO_DOSLib,d7    ; Alert! No DOS!
  231.     SYS    Alert            ; Show alert
  232.     move.l    #RETURN_FAIL,d0        ; Return failure
  233.     rts                ; And end
  234.  
  235.  .dos_ok:
  236.     cmp.w    #36,LIB_VERSION(a6)    ; Do we have OS 2.04+?
  237.     bgt    .os_ok            ; Yep
  238.  
  239.     move.l    a3,a6            ; Get DOSBase
  240.     SYS    Output            ; Get output handle
  241.     move.l    d0,d1
  242.     beq.b    .no_out            ; No output
  243.  
  244.     lea    NeedOS2_Msg(pc),a0    ; We need OS 2.04+
  245.     move.l    a0,d2
  246.     move.l    #NeedOS2_SIZEOF,d3    ; Size of message
  247.     SYS    Write            ; Inform user about problem
  248.  .no_out:
  249.     moveq    #ERROR_INVALID_RESIDENT_LIBRARY,d0
  250.     move.l    d0,pr_Result2(a5)    ; Set secondary result
  251.     move.l    #RETURN_FAIL,d0        ; Return failure
  252.     rts                ; And end
  253.  
  254.  .os_ok:
  255.     move.l    #dt_SIZEOF,d0        ; Size of data struct
  256.     move.l    #MEMF_CLEAR,d1        ; Clear the memory
  257.     SYS    AllocVec        ; Try to allocate DataTable
  258.     tst.l    d0            ; Got it?
  259.     bne.b    .mem_ok            ; Yep
  260.  
  261.     move.l    a3,a6            ; DOSBase
  262.     move.l    #ERROR_NO_FREE_STORE,d1    ; Ran out of memory
  263.     lea    PrgName_Msg(pc),a0
  264.     move.l    a0,d2            ; Header for error message
  265.     SYS    PrintFault        ; Show error message
  266.     move.l    #ERROR_NO_FREE_STORE,d1    ; Ran out of memory
  267.     SYS    SetIoErr        ; Set return code
  268.     move.l    #RETURN_FAIL,d0        ; Return failure
  269.     rts                ; End
  270.  
  271.  .mem_ok:
  272.     move.l    d0,a4            ; Get data structure
  273.     move.l    a3,dt_DOSBase(a4)    ; Init some data
  274.     move.l    a6,dt_SysBase(a4)
  275.     move.l    sp,dt_InitialSP(a4)
  276.     CALL    Main            ; Call main part
  277.     move.l    #RETURN_OK,d0        ; Ok return
  278.     CLD    1            ; Fall through to CleanExit
  279.  
  280.  
  281. *
  282. * CleanExit( __D0 ULONG code, __D1 ULONG res2 );
  283. *
  284. * Clean up everything and exit gracefully. IoErr() will be set to res2.
  285. * code is returned to the user. This function never returns.
  286. *
  287.  
  288. CleanExit
  289.  
  290.     move.l    dt_DOSBase(a4),a6    ; Get DOSBase
  291.     move.l    dt_InitialSP(a4),sp    ; Restore original SP
  292.     move.l    d0,d6            ; Save error codes
  293.     move.l    d1,d7
  294.     lea    CursorOn_Msg(pc),a0
  295.     move.l    a0,d1
  296.     SYS    PutStr            ; Restore cursor, if hidden
  297.     move.l    dt_RdArgs(a4),d1    ; Any RDArgs structure?
  298.     beq.b    .no_rdargs        ; No
  299.  
  300.     SYS    FreeArgs        ; Free RDArgs structure
  301.  .no_rdargs:
  302.      tst.b    dt_InOpened(a4)        ; Have we opened the in file?
  303.     beq.b    .no_in            ; No
  304.  
  305.     move.l    dt_InFile(a4),d1    ; Any input file left open?
  306.     beq.b    .no_in            ; No
  307.  
  308.     SYS    Close            ; Close input file
  309.  .no_in:
  310.      tst.b    dt_OutOpened(a4)    ; Have we opened the out file?
  311.     beq.b    .no_out            ; No
  312.  
  313.     move.l    dt_OutFile(a4),d1    ; Any output file left open?
  314.     beq.b    .no_out            ; No
  315.  
  316.     SYS    Close            ; Close output file
  317.  .no_out:
  318.      tst.b    dt_Matching(a4)        ; Any unbalanced MatchFirst()?
  319.     beq.b    .no_match        ; Nope
  320.  
  321.     lea    dt_AP(a4),a0
  322.     move.l    a0,d1            ; AnchorPath
  323.     SYS    MatchEnd        ; Clean up matching stuff
  324.  .no_match:
  325.     move.l    a6,a3            ; Save DOSBase
  326.     move.l    dt_SysBase(a4),a6
  327.     move.l    a4,a1            ; Get DataTable
  328.     SYS    FreeVec            ; Free it
  329.     exg    a3,a6            ; Get DOSBase again
  330.     move.l    d7,d1            ; Get secondary result
  331.     SYS    SetIoErr        ; Set result2
  332.     move.l    a6,a1            ; DOSBase
  333.     move.l    a3,a6            ; SysBase
  334.     SYS    CloseLibrary        ; Close dos.library
  335.     move.l    d6,d0            ; Get return code
  336.     rts                ; And exit
  337.  
  338.  
  339. *
  340. * VOID PrintFault( __A0 header, __D0 ULONG result2 );
  341. *
  342. * Print reason for failure and exit.
  343. *
  344.  
  345. PrintFault
  346.  
  347.     move.l    d0,d1
  348.     move.l    d1,d3            ; Save result2
  349.     move.l    a0,d2            ; Error header
  350.     SYS    PrintFault        ; Print message
  351.     move.l    #RETURN_FAIL,d0        ; Return code
  352.     move.l    d3,d1            ; And reason for it
  353.     CALL    CleanExit        ; Exit
  354.  
  355.  
  356. *
  357. * Main part. All "basic" data have been properly set up
  358. *
  359.  
  360. Main    move.l    dt_DOSBase(a4),a6    ; We use DOS a lot
  361.  
  362.     ** Set some default values **
  363.  
  364.     move.w    #FILENAMESIZE,dt_AP+ap_Strlen(a4)
  365.     move.l    #SIGBREAKF_CTRL_C,dt_AP+ap_BreakBits(a4)
  366.     move.w    #DEFWIDTH,dt_Width(a4)
  367.     move.w    #INITYPOS,dt_YPos(a4)
  368.  
  369.     ** Parse arguments **
  370.  
  371.     lea    Template_Msg(pc),a0
  372.     move.l    a0,d1            ; Template
  373.     lea    dt_Flags(a4),a0
  374.     move.l    a0,d2            ; Flags array
  375.     CLD    3            ; No RDArgs structure
  376.     SYS    ReadArgs        ; Parse arguments
  377.     move.l    d0,dt_RdArgs(a4)    ; Save RDArgs struct
  378.     bne.b    .args_ok        ; No errors
  379.  
  380.     SYS    IoErr            ; Why failure?
  381.     lea    PrgName_Msg(pc),a0
  382.     CALL    PrintFault
  383.  
  384.  .args_ok:
  385.     tst.l    dt_Flags+f_Hex(a4)    ; Only hex part?
  386.     beq.b    .no_hex            ; No
  387.  
  388.     move.b    #HEX,dt_DisplayFormat(a4)    ; Only show hex part
  389.  .no_hex:
  390.     tst.l    dt_Flags+f_Ascii(a4)    ; Only Ascii part?
  391.     beq.b    .no_ascii        ; No
  392.  
  393.     move.b    #ASCII,d0        ; Default is Ascii mode
  394.     cmp.b    #HEX,dt_DisplayFormat(a4)    ; Hex mode already requested?
  395.     bne.b    .no_ascii_hex        ; Nope
  396.  
  397.     move.b    #BOTH,d0        ; Else use Both mode
  398.  .no_ascii_hex:
  399.     move.b    d0,dt_DisplayFormat(a4)    ; Set display mode
  400.  .no_ascii:
  401.     move.l    dt_Flags+f_Width(a4),d0    ; Any width pointer?
  402.     beq.b    .no_width        ; No
  403.  
  404.     move.l    d0,a0            ; Get pointer
  405.     move.l    (a0),d1            ; And the value
  406.     move.w    d1,dt_Width(a4)        ; Save it
  407.  .no_width:
  408.     lea    MinWidthArray(pc),a0    ; Get array for finding proper value
  409.     CLD    0
  410.     move.b    dt_DisplayFormat(a4),d0    ; Get display format
  411.     tst.l    dt_Flags+f_NoOffset(a4)    ; Any offset?
  412.     beq.b    .offset            ; Yep
  413.  
  414.     add.w    #NOOFFSET,d0        ; Add no offset value
  415.  .offset:
  416.     add.w    d0,d0            ; Make value index words
  417.     move.w    (a0,d0.w),d0        ; Get minimal width
  418.     move.w    d0,dt_MinWidth(a4)    ; Save value
  419.     move.w    dt_Width(a4),d1        ; To small?
  420.     cmp.w    d0,d1
  421.     bge.b    .min_ok            ; No
  422.  
  423.  .size_err:
  424.     lea    WidthError_Msg(pc),a0    ; Format string
  425.     CALL    Printf1            ; Show error message
  426.     move.l    #RETURN_FAIL,d0        ; Return failure
  427.     CLD    1            ; No suitable ERROR_* code
  428.     CALL    CleanExit        ; Exit
  429.  
  430.  .min_ok:
  431.     cmp.w    #MAXWIDTH,d1        ; To large?
  432.     bgt.b    .size_err        ; Yes
  433.  
  434.     ** Open TO file, if any **
  435.  
  436.     move.l    dt_Flags+f_To(a4),d1    ; Any TO file?
  437.     beq    .no_to            ; Nope
  438.  
  439.     move.l    #MODE_NEWFILE,d2    ; Default is create the file
  440.     tst.l    dt_Flags+f_Append(a4)    ; Append to file?
  441.     beq.b    .del_old        ; No
  442.  
  443.     move.l    #MODE_READWRITE,d2    ; Don't erase any old file
  444.  
  445.  .del_old:
  446.     SYS    Open            ; Try to open it
  447.     move.l    d0,dt_OutFile(a4)    ; Save pointer
  448.     bne.b    .to_ok            ; TO file opened ok
  449.  
  450.     SYS    IoErr            ; Get error code
  451.     move.l    d0,d3            ; Save it
  452.     move.l    dt_Flags+f_To(a4),d0    ; Get TO file
  453.     lea    NoToFile_Msg(pc),a0    ; Format string
  454.     CALL    Printf1            ; Print error message
  455.     move.l    d3,d0            ; IoErr() error code
  456.     CLA    0            ; Header already printed
  457.     CALL    PrintFault
  458.  
  459.  .to_ok:
  460.     st    dt_OutOpened(a4)    ; Flag that we have opened the out file
  461.     tst.l    dt_Flags+f_Append(a4)    ; Append to file?
  462.     beq.b    .out_ok            ; No
  463.  
  464.     move.l    #0,d1
  465.     SYS    SetIoErr        ; Clear error code
  466.     move.l    dt_OutFile(a4),d1    ; File
  467.     move.l    #0,d2            ; Offset
  468.     move.l    #OFFSET_END,d3        ; Seek to end of file
  469.     SYS    Seek
  470.     move.l    d0,d3            ; Save current pos
  471.     SYS    IoErr            ; Get error code
  472.     moveq    #-1,d1
  473.     cmp.l    d1,d3            ; Seek ok?
  474.     beq.b    .seek_error        ; No
  475.  
  476.     tst.l    d0            ; Any error?
  477.     beq.b    .out_ok            ; No
  478.  
  479.  .seek_error:
  480.     move.l    d0,d3
  481.     move.l    dt_Flags+f_To(a4),d0    ; Get TO file
  482.     lea    NoAppend_Msg(pc),a0    ; Format string
  483.     CALL    Printf1            ; Print error message
  484.     move.l    d3,d0            ; IoErr() error code
  485.     CLA    0            ; Header already printed
  486.     CALL    PrintFault
  487.  
  488.  .no_to:
  489.     SYS    Output            ; Get standard output
  490.     move.l    d0,dt_OutFile(a4)    ; Save pointer
  491.     bne.b    .out_ok
  492.  
  493.     move.l    #RETURN_FAIL,d0        ; Return failure
  494.     CLD    1            ; Dunno why this should happen.. :)
  495.     CALL    CleanExit        ; Exit
  496.  
  497.  .out_ok:
  498.     move.l    dt_OutFile(a4),d1    ; Output file
  499.     SYS    IsInteractive        ; Interactive file?
  500.     tst.l    d0
  501.     bne.b    .match            ; Yep
  502.  
  503.     clr.l    dt_Flags+f_Page(a4)    ; Disable pager
  504.     st    dt_Flags+f_Cursor(a4)    ; Make it != NULL
  505.  
  506.     ** Do all pattern matching **
  507.  
  508.  .match:
  509.     move.l    dt_Flags+f_Files(a4),a3    ; Get files array
  510.     lea    dt_AP(a4),a2        ; Get AnchorPath struct
  511.  
  512.     ** Walk through all FILE arguments **
  513.  
  514.  .next_file:
  515.     tst.l    (a3)            ; End of filename array?
  516.     beq    .done            ; Yep
  517.  
  518.     ** And pattern match this argument **
  519.  
  520.     move.l    (a3)+,d1        ; Get name/pattern
  521.     move.l    a2,d2            ; AnchorPath
  522.     SYS    MatchFirst        ; Start matching this name
  523.     st    dt_Matching(a4)        ; We have called MatchFirst()
  524.     tst.l    d0
  525.     bne.b    .error            ; Error!
  526.  
  527.  .next_match:
  528.     tst.l    ap_Info+fib_DirEntryType(a2)    ; Type of entry?
  529.     beq.b    .matchnext        ; Not file, nor dir (??)
  530.  
  531.     ble.b    .file            ; A file
  532.  
  533.     bclr    #APB_DIDDIR,ap_Flags(a2)    ; Just did a dir?
  534.     bne.b    .matchnext        ; Yep, continue processing
  535.  
  536.     tst.l    dt_Flags+f_All(a4)    ; Enter directories?
  537.     beq.b    .matchnext        ; Nope
  538.  
  539.     bset    #APB_DODIR,ap_Flags(a2)    ; Else enter dir
  540.     bra.b    .matchnext        ; And continue
  541.  
  542.  .file:    CALL    DumpFile        ; Handle that file
  543.  
  544.  .matchnext:
  545.     move.l    a2,d1            ; AnchorPath
  546.     SYS    MatchNext        ; Do next file
  547.     tst.l    d0            ; Everything ok?
  548.     beq.b    .next_match        ; Yep
  549.  
  550.  .error:
  551.     move.l    d0,d7            ; Save error code
  552.     move.l    a2,d1            ; AnchorPath
  553.     SYS    MatchEnd        ; End matching
  554.     sf    dt_Matching(a4)        ; MatchFirst() "syncronised"
  555.     cmp.l    #ERROR_NO_MORE_ENTRIES,d7    ; Done with this round?
  556.     beq    .next_file        ; Yep, do next file
  557.  
  558.     cmp.l    #ERROR_BREAK,d7        ; Break'ed?
  559.     bne.b    .no_break        ; No
  560.  
  561.     CALL    PrintBreak        ; Print break message
  562.     move.l    #RETURN_OK,d0        ; Return Ok
  563.     CLD    1
  564.     CALL    CleanExit        ; Exit
  565.  
  566.  .no_break:
  567.     move.l    d7,d0            ; Failure reason
  568.     lea    PrgName_Msg(pc),a0
  569.     CALL    PrintFault
  570.  
  571.  .done:    move.l    dt_Flags+f_Files(a4),a0    ; Get filenames array
  572.     tst.l    (a0)            ; Any files specified at all?
  573.     bne.b    .rts            ; Yep
  574.  
  575.     SYS    Input            ; Get standard input
  576.     move.l    d0,dt_InFile(a4)    ; Save handle
  577.     beq.b    .rts            ; No handle
  578.  
  579.     move.l    d0,d1
  580.     SYS    Flush            ; To be on the safe side (we are going to read)
  581.     CALL    HexDump            ; Dump the file
  582.  .rts:    rts
  583.  
  584.  
  585. *
  586. * DumpFile();
  587. *
  588. * Simply dump the file in the AnchorPath to dt_OutFile, using suitable
  589. * parameters (as found in the DataTable ). Prints a header if that was
  590. * requested. May exit if fatal error, breaked or similar.
  591. *
  592.  
  593. DumpFile
  594.  
  595.     PUSHM    d0-3/a0-2/a6
  596.     move.l    dt_DOSBase(a4),a6    ; We only use DOS calls here
  597.     lea    dt_AP+ap_Buf(a4),a2    ; Pathname buffer
  598.     move.l    a2,d1            ; File name
  599.     move.l    #MODE_OLDFILE,d2    ; Old file
  600.     SYS    Open            ; Try to open it
  601.     move.l    d0,dt_InFile(a4)    ; Save handle
  602.     bne.b    .open_ok        ; File opened ok
  603.  
  604.     SYS    IoErr            ; Why didn't file open?
  605.     move.l    d0,d3            ; Save reason
  606.     move.l    a2,d0            ; Argument
  607.     lea    NoInFile_Msg(pc),a0    ; Format string
  608.     CALL    Printf1            ; Print error message
  609.     move.l    d3,d0            ; Why file didn't open
  610.     CLA    0            ; No header
  611.     CALL    PrintFault        ; Print "reason"
  612.  
  613.  .open_ok:
  614.      st    dt_InOpened(a4)        ; We have opened the in file
  615.     tst.l    dt_Flags+f_Header(a4)    ; Show a header?
  616.     beq.b    .write_ok        ; No
  617.  
  618.     move.l    dt_OutFile(a4),d1    ; Output file
  619.     lea    Header_Msg(pc),a0
  620.     move.l    a0,d2            ; Format string
  621.     PUSH    a2            ; Argument
  622.     move.l    sp,d3            ; Pointer to argument array
  623.     SYS    VFPrintf        ; Print header
  624.     add.l    #4,sp            ; Restore stack
  625.     tst.l    d0            ; Write ok?
  626.     bgt.b    .write_ok        ; Yes
  627.  
  628.  .write_error:
  629.     SYS    IoErr            ; Get error message
  630.     lea    WriteError_Msg(pc),a0    ; Couldn't write
  631.     CALL    PrintFault
  632.  
  633.  .write_ok:
  634.     CALL    HexDump            ; Do it
  635.     move.l    dt_InFile(a4),d1    ; Input file
  636.     SYS    Close            ; Close it (can hardly fail, since we read the file... ;)
  637.     clr.l    dt_InFile(a4)        ; Clear pointer
  638.     sf    dt_InOpened(a4)        ; No infile opened by us
  639.     POPM
  640.     rts
  641.  
  642.  
  643. *
  644. * VOID HexDump( VOID );
  645. *
  646. * Dump dt_InFile on dt_OutFile. Gets its paramteres from the DataTable.
  647. * Checks height, width, paging (if so, when) etc.
  648. *
  649. * Register usage:
  650. * D7 - Bytes per row
  651. * D5 - Number of bytes in last read operation
  652. * A3 - Pointer in work buffer
  653. *
  654.  
  655. HexDump
  656.  
  657.     PUSHM    d0-7/a0-3/a6
  658.     move.l    dt_DOSBase(a4),a6    ; We only use DOS calls
  659.     CALL    CalcBytesPerRow        ; Get # of bytes that fits on one row
  660.     move.l    d0,d7            ; Save value
  661.     move.l    d7,d5            ; Need to init # of bytes read
  662.     clr.l    dt_BytePos(a4)        ; Start at byte 0 :)
  663.  
  664.     tst.l    dt_Flags+f_Cursor(a4)    ; Hide cursor?
  665.     bne.b    .next_row        ; No
  666.  
  667.     move.l    dt_OutFile(a4),d1    ; Output file
  668.     lea    CursorOff_Msg(pc),a0
  669.     move.l    a0,d2
  670.     SYS    FPuts            ; Hide cursor
  671.     tst.l    d0
  672.     beq.b    .next_row        ; No write error
  673.  
  674.  .write_error:
  675.     SYS    IoErr
  676.     lea    WriteError_Msg(pc),a0
  677.     CALL    PrintFault
  678.  
  679.  .next_row:
  680.     CALL    CheckBreak        ; Break pressed?
  681.     tst.l    d0
  682.     bne    .done            ; Yep, CTRL-D pressed
  683.  
  684.     cmp.l    d7,d5            ; Did last read fill whole buffer?
  685.     blt    .done            ; No, must be end of file
  686.  
  687.     ** Get data for next output line **
  688.  
  689.     CLD    1
  690.     SYS    SetIoErr        ; Clear IoErr() code
  691.     move.l    dt_InFile(a4),d1    ; Input file
  692.     lea    dt_ReadBuffer(a4),a0
  693.     move.l    a0,d2            ; Read buffer
  694.     move.l    #1,d3            ; Element size
  695.     move.l    d7,d4            ; Number of elements
  696.     SYS    FRead            ; Read data
  697.     move.l    d0,d5            ; Save amount read
  698.     SYS    IoErr            ; Get error code
  699.     tst.l    d0            ; Save it
  700.     ble.b    .read_ok        ; No error
  701.  
  702.  .read_error:
  703.     lea    ReadError_Msg(pc),a0
  704.     CALL    PrintFault
  705.  
  706.  .read_ok:
  707.     tst.l    d5            ; End of input?
  708.     beq    .done            ; Yep
  709.  
  710.     ** Build output string **
  711.  
  712.     lea    dt_WriteBuffer(a4),a3    ; Start of write buffer
  713.     lea    HexTable(pc),a0        ; Hex conversion table
  714.     move.l    #$0f,d1            ; Mask for hex conversion
  715.     move.l    #4,d2            ; Steps to shift for each char
  716.     tst.l    dt_Flags+f_NoOffset(a4)    ; Display offset?
  717.     bne.b    .no_offset        ; No
  718.  
  719.     move.l    dt_BytePos(a4),d0    ; Get current byte position
  720.     move.l    #5,d3            ; Count
  721.     add.l    #6,a3            ; Start char + 1
  722.  .make_offset:
  723.      move.l    d0,d4            ; Get value
  724.      lsr.l    d2,d0            ; Shift to next char
  725.      and.l    d1,d4            ; Get lower bits
  726.     move.b    0(a0,d4.w),-(a3)    ; Get hex char
  727.     dbra    d3,.make_offset        ; Loop back
  728.  
  729.     add.l    #6,a3            ; Go to end of converted text
  730.     move.b    #':',(a3)+
  731.     move.b    #' ',(a3)+
  732.  .no_offset:
  733.     cmp.b    #ASCII,dt_DisplayFormat(a4)    ; Only Ascii?
  734.     beq.b    .ascii            ; Yes
  735.  
  736.     lea    dt_ReadBuffer(a4),a1    ; Read buffer
  737. ;    lea    HexTable(pc),a0        ; Hex conversion table
  738. ;    move.l    #$0f,d1            ; Mask for hex conversion
  739. ;    move.l    #4,d2            ; Steps to shift for each char
  740.     move.l    #1,d3            ; Count
  741.     move.l    #3,d4            ; Space mask
  742.     CLD    0            ; Better clear work registers
  743.     CLD    6
  744.  .make_hex:
  745.     move.b    (a1)+,d6        ; Get char
  746.     move.l    d6,d0
  747.     lsr.l    d2,d0            ; Get high nybble
  748.     move.b    (a0,d0.w),(a3)+        ; Get hex char
  749.     and.l    d1,d6            ; Get low nybble
  750.     move.b    (a0,d6.w),(a3)+        ; Get hex char
  751.     move.l    d3,d0            ; Get offset in line
  752.     and.l    d4,d0            ; Mask out lower 2 bits
  753.     bne.b    .next_make_hex        ; No time for space
  754.  
  755.     move.b    #' ',(a3)+        ; Write a space
  756.  .next_make_hex:
  757.      add.l    #1,d3            ; Increase counter
  758.     cmp.l    d3,d5            ; All bytes on this row done?
  759.     bge.b    .make_hex        ; No
  760.  
  761.     clr.b    (a3)            ; NULL terminate string so far
  762.     cmp.b    #BOTH,dt_DisplayFormat(a4)    ; Both Ascii and Hex?
  763.     bne.b    .row_done        ; Nope, this row is finished
  764.  
  765.     lea    dt_WriteBuffer(a4),a0
  766.     add.w    dt_EndOfHex(a4),a0    ; Address of end of Hex-part
  767.     move.l    a0,d0
  768.     sub.l    a3,d0
  769.     bra.b    .start_pad
  770.  
  771.  .pad_space:
  772.     move.b    #' ',(a3)+        ; Pad out with spaces
  773.  .start_pad:
  774.      dbra    d0,.pad_space
  775.  
  776.  .ascii:
  777.     lea    dt_ReadBuffer(a4),a0    ; Read data
  778.     lea    AsciiTable(pc),a1    ; Conversion table
  779.     move.l    d5,d0            ; Bytes/line
  780.     sub.l    #1,d0            ; Prepare for dbra
  781.     CLD    1
  782.     move.b    #"'",(a3)+        ; Start of ascii part
  783.  .next_ascii:
  784.     move.b    (a0)+,d1        ; Get next byte
  785.     move.b    (a1,d1.w),(a3)+        ; Show proper char
  786.     dbra    d0,.next_ascii
  787.  
  788.     move.b    #"'",(a3)+        ; End of ascii part
  789.  .row_done:
  790.      move.b    #10,(a3)+        ; Place a linefeed at the end
  791.     clr.b    (a3)            ; And terminate the string
  792.     add.l    d5,dt_BytePos(a4)    ; Increment byte position counter
  793.     move.l    dt_OutFile(a4),d1    ; Output file
  794.     lea    dt_WriteBuffer(a4),a0
  795.     move.l    a0,d2            ; Write buffer
  796.     SYS    FPuts            ; Write out string
  797.     tst.l    d0            ; Write ok?
  798.     bmi    .write_error        ; No
  799.  
  800.     tst.l    dt_Flags+f_Page(a4)    ; Page output?
  801.     beq    .next_row        ; No
  802.  
  803.     tst.w    dt_Height(a4)        ; Any height?
  804.     beq    .next_row        ; No, something is wrong...
  805.  
  806.     ** Show a page prompt, and wait for response **
  807.  
  808.     add.w    #1,dt_YPos(a4)        ; Next row
  809.     move.w    dt_YPos(a4),d0
  810.     cmp.w    dt_Height(a4),d0    ; Time for a prompt?
  811.     bls    .next_row        ; No
  812.  
  813.     move.w    #INITYPOS,dt_YPos(a4)    ; Reset YPos
  814.     move.l    dt_OutFile(a4),d4
  815.     move.l    d4,d1            ; Output file
  816.     SYS    Flush            ; Make sure prompt is visible (and "enable" reading)
  817.     tst.l    d0            ; Write ok?
  818.     beq.b    .prompt_error        ; No
  819.  
  820.     move.l    d4,d1            ; Output file
  821.     move.l    #1,d2            ; Select RAW mode
  822.     SYS    SetMode            ; Go to RAW mode
  823.     tst.l    d0            ; All ok?
  824.     beq.b    .prompt_error        ; No
  825.  
  826.     move.l    d4,d1            ; Output file
  827.     lea    PagePrompt_Msg(pc),a0
  828.     move.l    a0,d2            ; Page prompt
  829.     SYS    FPuts            ; Show it
  830.     tst.l    d0            ; All ok
  831.     bge.b    .prompt_ok        ; Yep
  832.  
  833.  .prompt_error:
  834.      SYS    IoErr            ; Get failure reason
  835.      move.l    d0,d3            ; Save it
  836.     move.l    d4,d1            ; Output file
  837.     move.l    #0,d2            ; Go to CON mode
  838.     SYS    SetMode            ; Try to restore normal "CON" mode
  839.     move.l    d4,d1            ; Output file
  840.     lea    EndPrompt_Msg(pc),a0
  841.     move.l    a0,d2            ; Try to erase prompt
  842.     SYS    FPuts            ; Do it
  843.     move.l    d3,d0            ; Error code
  844.     lea    PromptError_Msg(pc),a0    ; Error eader
  845.     CALL    PrintFault
  846.  
  847.  .prompt_ok:
  848.     move.l    d4,d1            ; Output file
  849.     SYS    Flush            ; Make sure prompt is visible (and "enable" reading)
  850.     tst.l    d0            ; Write ok?
  851.     beq.b    .prompt_error        ; No
  852.  
  853.     move.l    d4,d1            ; Output file
  854.     lea    dt_Response(a4),a0
  855.     move.l    a0,d2            ; Read buffer
  856.     move.l    #1,d3            ; No. of bytes to read
  857.     SYS    Read            ; Wait for a keypress
  858.     move.l    d0,d6            ; Save read length
  859.     bmi.b    .prompt_error        ; Error!
  860.  
  861.     move.l    d4,d1            ; Output file
  862.     lea    EndPrompt_Msg(pc),a0
  863.     move.l    a0,d2            ; Remove prompt
  864.     SYS    FPuts            ; Do it
  865.     tst.l    d0            ; All ok?
  866.     bmi    .prompt_error        ; No
  867.  
  868.     move.l    d4,d1            ; Output file
  869.     SYS    Flush            ; Make sure prompt gets removed
  870.     tst.l    d0            ; All ok?
  871.     beq    .prompt_error        ; No
  872.  
  873.     move.l    d4,d1            ; Output file
  874.     move.l    #0,d2            ; Goto CON mode
  875.     SYS    SetMode            ; Restore normal console mode
  876.     tst.l    d0            ; All ok?
  877.     beq    .prompt_error        ; No
  878.  
  879.     tst.l    d6            ; Read ok?
  880.     beq.b    .file_break        ; EOF => File breaked
  881.  
  882.     tst.l    dt_Flags+f_Cursor(a4)    ; Hide cursor?
  883.     bne.b    .no_hide        ; No
  884.  
  885.     move.l    d4,d1            ; Output file
  886.     lea    CursorOff_Msg(pc),a0
  887.     move.l    a0,d2            ; Hide cursor
  888.     SYS    FPuts            ; Do it
  889.     tst.l    d0            ; All ok?
  890.     bmi    .prompt_error        ; No
  891.  
  892.  .no_hide:
  893.      CALL    CalcBytesPerRow
  894.      move.l    d0,d7
  895.     move.b    dt_Response(a4),d0    ; Get key user pressed
  896.     cmp.b    #3,d0            ; Ctrl-C?
  897.     beq    .break            ; Yep
  898.  
  899.     cmp.b    #4,d0            ; Ctrl-D?
  900.     bne.b    .0            ; No
  901.  
  902.  .file_break:
  903.     CALL    PrintFileBreak        ; Show break message
  904.     bra    .done            ; And end this file
  905.  
  906.  .0:    cmp.b    #27,d0            ; Esc?
  907.     beq    .break            ; Yep
  908.  
  909.     cmp.b    #'s',d0            ; Skip page prompts for this file
  910.     bne.b    .1
  911.  
  912.  .clr_height:
  913.     clr.w    dt_Height(a4)        ; Stop paging for this file
  914.     bra    .cont
  915.  
  916.  .1:    cmp.b    #'S',d0            ; Skip page prompts for this file
  917.     beq.b    .clr_height
  918.  
  919.     cmp.b    #8,d0            ; Backspace => Previous page
  920.     bne.b    .4
  921.  
  922.     CLD    1
  923.     SYS    SetIoErr        ; Clear any error code
  924.     CLD    0
  925.     move.w    dt_Height(a4),d0    ; Get height
  926.     add.w    d0,d0            ; * 2 (really skip 2 pages)
  927.     sub.w    #3,d0            ; A little overlap + page prompts space
  928.     mulu    d7,d0            ; Pager only active if this is != 0
  929.     sub.l    d0,dt_BytePos(a4)    ; Go backwards
  930.     bge.b    .seek_ok        ; No seek beyond start
  931.  
  932.     clr.l    dt_BytePos(a4)        ; Reset pos to start
  933.  .seek_ok:
  934.     move.w    #INITYPOS-1,dt_YPos(a4)    ; Reset YPos
  935.     move.l    dt_InFile(a4),d1    ; Input file
  936.     move.l    dt_BytePos(a4),d2    ; Offset to seek to
  937.     move.l    #OFFSET_BEGINNING,d3    ; Offset is relative to start
  938.     SYS    Seek            ; Do the seeking
  939.     move.l    d0,d3            ; Save result
  940.     SYS    IoErr            ; Any error?
  941.     exg.l    d0,d3
  942.     tst.l    d0            ; Check seek result
  943.     bmi    .read_error        ; Error!
  944.  
  945.     tst.l    d3            ; IoErr() returned error?
  946.     bne    .read_error        ; Yep
  947.  
  948.     lea    FF_Msg(pc),a0
  949.     move.l    dt_OutFile(a4),d1    ; Output file
  950.     move.l    a0,d2            ; Code to clear screen
  951.     SYS    FPuts            ; Clear it
  952.     tst.l    d0            ; All ok?
  953.     bmi    .write_error        ; Nope
  954.  
  955.     move.l    dt_OutFile(a4),d1    ; Output file
  956.     SYS    Flush            ; Make sure cursor is restored
  957.     tst.l    d0            ; All ok?
  958.     beq    .write_error        ; No
  959.  
  960.     bra.b    .cont            ; And continue with next row etc.
  961.  
  962.  .4:    cmp.b    #'=',d0            ; Disable page prompt for rest of files
  963.     bne.b    .2
  964.  
  965.     clr.l    dt_Flags+f_Page(a4)    ; Disable paging
  966.     bra.b    .cont
  967.  
  968.  .2:    cmp.b    #13,d0            ; Return (= new line)?
  969.      bne.b    .cont
  970.  
  971.     move.w    #30000,dt_YPos(a4)    ; Only do one line...
  972.  .cont:    bra    .next_row        ; And continue with next row
  973.  
  974.  .break:
  975.     CALL    PrintBreak        ; Break pressed
  976.     CLD    0            ; No error
  977.     CLD    1
  978.     CALL    CleanExit        ; Exit
  979.  
  980.     ** All done. Clean up and return **
  981.  
  982.  .done:
  983.     tst.l    dt_Flags+f_Cursor(a4)    ; Cursor hidden?
  984.     bne.b    .end            ; No
  985.  
  986.     move.l    dt_OutFile(a4),d1    ; Output file
  987.     lea    CursorOn_Msg(pc),a0
  988.     move.l    a0,d2            ; Restore cursor
  989.     SYS    FPuts            ; Do it
  990.     tst.l    d0            ; All ok?
  991.     bmi    .write_error        ; No
  992.  
  993.     move.l    dt_OutFile(a4),d1    ; Output file
  994.     SYS    Flush            ; Make sure cursor is restored
  995.     tst.l    d0            ; All ok?
  996.     beq    .write_error        ; No
  997.  .end:
  998.     POPM
  999.     rts
  1000.  
  1001.  
  1002. *
  1003. * LONG CalcBytesPerRow( VOID );
  1004. *
  1005. * Calculates the number of bytes that will fit on one row.
  1006. * Also sets the dt_Height variable properly (if possible).
  1007. *
  1008.  
  1009. CalcBytesPerRow
  1010.  
  1011.     PUSHM    d1-2
  1012.     CALL    GetWinSize        ; Try to get size of console window
  1013.     CLD    0
  1014.     CLD    1
  1015.     move.w    dt_Width(a4),d0        ; Get requested width of line
  1016.     tst.l    dt_Flags+f_NoOffset(a4)    ; Show offset?
  1017.     bne.b    .offset            ; No
  1018.  
  1019.     sub.w    #8,d0            ; Make room for offset
  1020.     moveq    #8,d1
  1021.  .offset:
  1022.     cmp.b    #ASCII,dt_DisplayFormat(a4)    ; Only Ascii?
  1023.     bne.b    .not_ascii        ; No
  1024.  
  1025.     sub.w    #2,d0            ; For the single-quotes
  1026.     bra.b    .bytes_done
  1027.  
  1028.  .not_ascii:
  1029.     cmp.b    #HEX,dt_DisplayFormat(a4)    ; Only Hex?
  1030.     bne.b    .both            ; No
  1031.  
  1032.     lsl.w    #2,d0            ; * 4
  1033.     divu    #9,d0            ; And make it bytes/row
  1034.     bra.b    .bytes_done
  1035.  
  1036.  .both:    sub.w    #2,d0            ; Remove some space (single-quotes)
  1037.     lsl.w    #2,d0            ; * 4
  1038.     divu    #13,d0            ; And make it bytes/row
  1039.     CLD    2
  1040.     move.w    d0,d2
  1041.     lsl.w    #3,d2            ; * 8
  1042.     add.w    d0,d2            ; And add old value again => * 9
  1043.     lsr.w    #2,d2            ; / 4
  1044.     add.w    d2,d1            ; Add hex part
  1045.     move.w    d0,d2
  1046.     and.w    #3,d2            ; Even multiple of 4?
  1047.     beq.b    .bytes_done        ; Yep
  1048.  
  1049.     addq.w    #1,d1
  1050.  
  1051.  .bytes_done:
  1052.      move.w    d1,dt_EndOfHex(a4)    ; Save end pos for hex part
  1053.     and.l    #$0000ffff,d0        ; Clear upper word
  1054.      POPM
  1055.      rts
  1056.  
  1057.  
  1058. *
  1059. * LONG CheckBreak( VOID );
  1060. *
  1061. * Check if Ctrl-C or Ctrl-D have been pressed. If Ctrl-C, exit "normally".
  1062. * If Ctrl-D, print that a file break occured, and return TRUE. Else
  1063. * return FALSE.
  1064. *
  1065.  
  1066. CheckBreak
  1067.  
  1068.     PUSHM    d1/a0-1/a6
  1069.     move.l    dt_SysBase(a4),a6
  1070.     CLD    0
  1071.     move.l    #SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D,d1    ; Bits we are checking
  1072.     SYS    SetSignal        ; Check which signals we have got
  1073.     btst    #SIGBREAKB_CTRL_C,d0    ; Ctrl-C pressed?
  1074.     beq.b    .no_c            ; No
  1075.  
  1076.     CALL    PrintBreak
  1077.     CLD    0
  1078.     CLD    1
  1079.     CALL    CleanExit
  1080.  
  1081.  .no_c:
  1082.     CLD    1            ; Default return is FALSE
  1083.      btst    #SIGBREAKB_CTRL_D,d0    ; Ctrl-D pressed?
  1084.      beq.b    .done            ; No
  1085.  
  1086.     CALL    PrintFileBreak
  1087.     move.l    #1,d1
  1088.  .done:
  1089.     move.l    d1,d0            ; Get return code
  1090.     POPM
  1091.     rts
  1092.  
  1093.  
  1094. *
  1095. * VOID GetWinSize( VOID );
  1096. *
  1097. * Set the dt_Width and dt_Height fields properly.
  1098. * If this routine discovers that dt_Width becomes to small
  1099. * (i.e. output window is too narrow), this routine will exit with
  1100. * a suitable message.
  1101. *
  1102.  
  1103. REPORTBUF    EQU    16
  1104.  
  1105. GetWinSize
  1106.  
  1107.     PUSHM    d0-4/a0-1/a6
  1108.     tst.l    dt_Flags+f_Width(a4)    ; Width specified?
  1109.     beq.b    .get            ; Nope, get suitable value
  1110.  
  1111.     tst.l    dt_Flags+f_Page(a4)    ; Page output?
  1112.     beq    .end            ; No, no need to do anything..
  1113.  
  1114.  .get:    move.l    dt_OutFile(a4),d4    ; Output file
  1115.     move.l    d4,d1
  1116.     SYS    IsInteractive,dt_DOSBase(a4)
  1117.     tst.l    d0            ; Interactive?
  1118.     beq    .no_page        ; No
  1119.  
  1120.     move.l    d4,d1            ; Output file
  1121.     SYS    Flush
  1122.     tst.l    d0            ; All ok?
  1123.     beq    .restore_mode        ; No
  1124.  
  1125.     move.l    d4,d1            ; Output file
  1126.     move.l    #1,d2            ; RAW mode
  1127.     SYS    SetMode
  1128.     tst.l    d0            ; Ok?
  1129.     beq    .end            ; No
  1130.  
  1131.     move.l    d4,d1            ; Output file
  1132.     lea    GetWinBounds_Msg(pc),a0
  1133.     move.l    a0,d2            ; Ask for window bounds report
  1134.     move.l    #GetWinBounds_Len,d3    ; Length of string
  1135.     SYS    Write            ; Write string
  1136.     tst.l    d0            ; All ok
  1137.     bmi    .restore_mode        ; No!
  1138.  
  1139.     move.l    d4,d1            ; Output file
  1140.     move.l    #10000,d2        ; Wait .1 secs
  1141.     SYS    WaitForChar        ; Wait for reply on request
  1142.     tst.l    d0            ; Anything in return?
  1143.     beq    .restore_mode        ; No, no need waiting..
  1144.  
  1145.     sub.l    #REPORTBUF,sp        ; Get stack space for report
  1146.     move.l    d4,d1            ; Output file
  1147.     move.l    sp,d2            ; Read buffer
  1148.     move.l    #REPORTBUF,d3        ; Size of buffer
  1149.     SYS    Read            ; Get report
  1150.     move.l    d0,d3            ; Number of chars read
  1151.     move.l    d4,d1            ; Output file
  1152.     move.l    #0,d2            ; CON mode
  1153.     SYS    SetMode            ; Goto CON mode
  1154.     cmp.l    #9,d3            ; Less than 8 chars read?
  1155.     ble    .bad_report        ; Yep, bad report
  1156.  
  1157.     move.l    sp,a0            ; Input buffer
  1158.     cmp.b    #';',4(a0)        ; A valid return?
  1159.     bne.b    .bad_report        ; No
  1160.  
  1161.     cmp.b    #'r',-1(a0,d3.w)    ; More validations..
  1162.     bne.b    .bad_report
  1163.  
  1164.     add.l    #5,a0            ; Get first char of y size
  1165.     CLD    0
  1166.     move.b    (a0)+,d0        ; Get first char
  1167.     sub.w    #'0',d0            ; Make it "normal" number
  1168.     cmp.b    #';',(a0)        ; More Y?
  1169.     beq.b    .x            ; No
  1170.  
  1171.     mulu    #10,d0
  1172.     add.b    (a0)+,d0        ; Next char
  1173.     sub.b    #'0',d0            ; Convert to number
  1174.     cmp.b    #';',(a0)        ; More Y?
  1175.     beq.b    .y_done            ; No
  1176.  
  1177.     mulu    #10,d0            ; We limit y size to 999 lines... :)
  1178.     add.b    (a0)+,d0        ; Get last char
  1179.     sub.b    #'0',d0            ; And convert it
  1180.  .y_done:
  1181.      tst.l    dt_Flags+f_Page(a4)    ; Page output?
  1182.     beq.b    .x            ; No
  1183.  
  1184.     move.w    d0,dt_Height(a4)    ; Save height
  1185.  .x:    tst.l    dt_Flags+f_Width(a4)    ; Width specified?
  1186.     bne.b    .bad_report        ; Yep, ignore this part
  1187.  
  1188.     addq.l    #1,a0            ; Skip separator
  1189.     CLD    0
  1190.     move.b    (a0)+,d0        ; Get first char
  1191.     cmp.b    #' ',d0            ; Bad one?
  1192.     beq.b    .report_done        ; Yes
  1193.  
  1194.     cmp.b    #';',d0            ; Bad?
  1195.     beq.b    .report_done        ; Yes
  1196.  
  1197.     cmp.b    #'r',d0            ; Bad?
  1198.     beq.b    .report_done        ; Yes
  1199.  
  1200.     sub.b    #'0',d0            ; Make it "normal"
  1201.     cmp.b    #' ',(a0)        ; Any more proper char?
  1202.     beq.b    .report_done        ; No
  1203.  
  1204.     mulu    #10,d0
  1205.     add.b    (a0)+,d0        ; Next char
  1206.     sub.b    #'0',d0            ; Make it "normal"
  1207.     cmp.b    #' ',(a0)        ; End of report?
  1208.     beq.b    .report_done        ; Yep
  1209.  
  1210.     add.b    (a0)+,d0        ; Get last char
  1211.     sub.b    #'0',d0
  1212.  .report_done:
  1213.     move.w    d0,dt_Width(a4)        ; Save width
  1214.  .bad_report:
  1215.     add.l    #REPORTBUF,sp        ; Restore stack
  1216.  .end:    POPM
  1217.     rts
  1218.  
  1219.  .restore_mode:
  1220.     move.l    d4,d1            ; Output file
  1221.     move.l    #0,d2            ; RAW mode
  1222.     SYS    SetMode
  1223.     bra.b    .end
  1224.  
  1225.  .no_page:
  1226.     clr.l    dt_Flags+f_Page(a4)    ; Disable page prompts
  1227.     st    dt_Flags+f_Cursor(a4)    ; Make Flags.Cursor != NULL
  1228.     bra.b    .end
  1229.  
  1230.  
  1231. *
  1232. * LONG Printf1( __A0 STRPTR format, __D0 ULONG arg1 );
  1233. *
  1234. * Printf format using arg1 as the only argument in the argument array.
  1235. * The return is the return value from VPrintf.
  1236. *
  1237.  
  1238. Printf1
  1239.  
  1240.     PUSHM    d1-2/a0-1/a6
  1241.     move.l    dt_DOSBase(a4),a6
  1242.     PUSH    d0            ; Save argument
  1243.     move.l    a0,d1            ; Format
  1244.     move.l    sp,d2            ; Argument array
  1245.     SYS    VPrintf            ; Print string
  1246.     addq.l    #4,sp            ; Restore stack
  1247.     POPM
  1248.     rts
  1249.  
  1250.  
  1251. *
  1252. * VOID PrintBreak( VOID );
  1253. *
  1254. * Simply print out a break message. May exit, if write failed.
  1255. *
  1256.  
  1257. PrintBreak
  1258.  
  1259.     PUSH    a0
  1260.     lea    Break_Msg(pc),a0    ; Format string
  1261.     CALL    __PrintBreakDummy
  1262.     POP
  1263.     rts
  1264.  
  1265.  
  1266. *
  1267. * VOID PrintFileBreak( VOID );
  1268. *
  1269. * Simply print out a file break message. May exit, if write failed.
  1270. *
  1271.  
  1272. PrintFileBreak
  1273.  
  1274.     PUSH    a0
  1275.     lea    FileBreak_Msg(pc),a0    ; Format string
  1276.     CALL    __PrintBreakDummy
  1277.     POP
  1278.     rts
  1279.  
  1280.  
  1281. *
  1282. * VOID __PrintBreakDummy( __A0 STRPTR msg );
  1283. *
  1284. * "Dummy" for printing break messages.
  1285. *
  1286.  
  1287. __PrintBreakDummy
  1288.  
  1289.     PUSHM    d0/a1/a6
  1290.     lea    CursorOn_Msg(pc),a1    ; Argument
  1291.     move.l    a1,d0
  1292.     CALL    Printf1            ; Print error message
  1293.     tst.l    d0            ; All ok?
  1294.     bge.b    .end            ; Yep
  1295.  
  1296.     move.l    dt_DOSBase(a4),a6
  1297.     SYS    IoErr            ; Reason for failure
  1298.     lea    PrgName_Msg(pc),a0
  1299.     CALL    PrintFault
  1300.  
  1301.  .end:    POPM
  1302.     rts
  1303.  
  1304.  
  1305. MinWidthArray
  1306.     MINWIDTHARRAY
  1307.  
  1308. *
  1309. * Start of string section
  1310. *
  1311.  
  1312.     dc.b    "$VER: HexD 2.0 (21.02.93)",0
  1313.  
  1314. DOSName_Msg
  1315.     dc.b    "dos.library",0
  1316.  
  1317. PrgName_Msg
  1318.     dc.b    "HexD",0
  1319.  
  1320. Template_Msg
  1321.     TEMPLATE
  1322.  
  1323. Header_Msg
  1324.     dc.b    "==== File ""%s"" ====",10,0
  1325.  
  1326. MAX3    SET    MAXWIDTH/100
  1327. MAX2    SET    (MAXWIDTH-MAX3*100)/10
  1328. MAX1    SET    MAXWIDTH-MAX2*10-MAX3*100
  1329.  
  1330. WidthError_Msg
  1331.     dc.b    "HexD: WIDTH out of range (allowed range: %ld - "
  1332.     dc.b    MAX3+'0',MAX2+'0',MAX1+'0',")",10,0
  1333.  
  1334. NoToFile_Msg
  1335.     dc.b    "HexD: Couldn't open TO file ""%s"":",10,0
  1336.  
  1337. NoAppend_Msg
  1338.     dc.b    "HexD: Couldn't append to TO file ""%s"":",10,0
  1339.  
  1340. NoInFile_Msg
  1341.     dc.b    "HexD: Couldn't open ""%s"" for input:",10,0
  1342.  
  1343. WriteError_Msg
  1344.     dc.b    "HexD: Write error",0
  1345.  
  1346. ReadError_Msg
  1347.     dc.b    "HexD: Read error",0
  1348.  
  1349. PromptError_Msg
  1350.     dc.b    "HexD: Prompt error",0
  1351.  
  1352. NarrowWindow_Msg
  1353.     dc.b    "HexD: Output window is too narrow",10,0
  1354.  
  1355. NeedOS2_Msg
  1356.     dc.b    "HexD: You need OS 2.04+",10,0
  1357.  
  1358. NeedOS2_SIZEOF    EQU    *-NeedOS2_Msg
  1359.  
  1360. PagePrompt_Msg
  1361.     dc.b    13,$9b,"7m  --More--  "
  1362.     dc.b    $9b,$30,$20,$70,$0
  1363.  
  1364. EndPrompt_Msg
  1365.     dc.b    $9b,"0m",13,$9b,"K",0
  1366.  
  1367. Break_Msg
  1368.     dc.b    "%sHexD: ***Break",10,0
  1369.  
  1370. FileBreak_Msg
  1371.     dc.b    "%sHexD: ***File break",10,0
  1372.  
  1373. CursorOn_Msg
  1374.     dc.b    $9b,$20,$70,$0
  1375.  
  1376. CursorOff_Msg
  1377.     dc.b    $9b,$30,$20,$70,$0
  1378.  
  1379. GetWinBounds_Msg
  1380.     dc.b    $9b,"0 q",0
  1381. GetWinBounds_Len    EQU    *-GetWinBounds_Msg
  1382.  
  1383. FF_Msg    dc.b    12,0
  1384.  
  1385. AsciiTable
  1386.     dc.b    "································ !""#$%&'()*+,-./0123456789"
  1387.     dc.b    ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst"
  1388.     dc.b    "uvwxyz{|}~································· ¡¢£¤¥¦§¨©ª«¬­®¯"
  1389.     dc.b    "°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéê"
  1390.     dc.b    "ëìíîïðñòóôõö÷øùúûüýþÿ",0
  1391.  
  1392. HexTable
  1393.     dc.b    "0123456789abcdef",0
  1394.  
  1395.     END
  1396.